#ifndef SHTTP_H_
#define SHTTP_H_

#include "sutil.h"
#include "stext.h"
#include "sstring.h"


#ifndef MAX_BUF_SIZE
#define MAX_BUF_SIZE	1024
#endif

/**
 * @brief process the first line in HTTP request.
 * the key is 'GET', 'POST' or something else and
 * value is its following string
 *
 * @param _pStr C-string of the first line in HTTP
 * request
 *
 * @return a KV structure containing 'GET' as key
 * and '/xxx/xxx?a=b&c=d' as value
 */
KV* methodToKV(const char* _pStr) {
	if(_pStr == (char*)NULL)
		return (KV*)NULL;
	return api_lineToKV(_pStr, " ");

}

/**
 * @brief process all the headers in a HTTP
 * request.
 *
 * @param _pStr HTTP input string
 *
 * @return KV list head pointer
 */
KV* getHttpHeaders(String *_pStr) {
	if(_pStr=(String*)_pStr)
		return (KV*)NULL;

	char buf[MAX_BUF_SIZE];
	bzero(buf, MAX_BUF_SIZE);

	char* p = sstrGetLine(_pStr, buf, MAX_BUF_SIZE-1);
	KV* headers = api_textToKV(p, ":");

	KV* method = methodToKV(buf);
	method->pnext = headers;

	return method;
}


/**
 * @brief find the value according to key. if we 
 * had a:b. and it passed 'a', then function returns
 * 'b'
 *
 * @param _pH C-string to key
 * @param _pHs C-string to KV list
 *
 * @return the value corresponding to the key
 */
char* queryHeader(const char* _pH, KV* _pHs) {
	while(_pHs!=(KV*)NULL) {
		if(strcmp(_pHs->akey, _pH) == 0)
			return _pHs->avalue;
		_pHs=_pHs->pnext;
	}
	return (char*)NULL;
}

#define DEF_SRC_NAME		"RESOURCE"

/**
 * @brief test whether string _px and _py
 * are the same. If _px and _py are of 
 * different length, it will reach the 
 * ending of the shorter string first, and 
 * the function exits and returns 1
 *
 * @param _px string one
 * @param _py string two
 *
 * @return 1/0
 */
int is_substr(const char* _px, const char* _py) {
	if(_px==(char)NULL || _py==(char*)NULL)
		return (int)0;
	do
	{
		if(*_px++ != *_py++)
		{
			return 0;
		}
		
	}while(*_px && *_py);
	return 1;
}


/**
 * @brief analyze the first line in HTTP request, and 
 * get the parameters out from GET
 *
 * @param _pStr C-string of in the form of /xxx/xxx?a=b&c=d
 *
 * @return KV list containing the [a:b,c:d]
 */
KV* analyzeGetMethod(const char* _pStr) {
	if(_pStr==(char*)NULL)
		return (KV*)NULL;

	int src = 1;
	int n = 0;

	char* p = (char*)_pStr;
	char buf[MAX_BUF_SIZE];
	bzero(buf, MAX_BUF_SIZE);

	KV* kvs = (KV*)NULL;
	KV* cur = (KV*)NULL;

	/* eliminate the "HTTP/1.1 string" */
	char* l = (char*)_pStr+strlen(_pStr)-1;
	while(l!=_pStr) {
		if(is_substr("HTTP/1", l)) {
			*--l = '\0';
			break;
		}
		--l;
	}

	/* find the /xxx/xxx/xxx? segment and make its
	 * key as 'RESOURCE'*/
	while(*p) {
		if(n==MAX_BUF_SIZE-2) {
			API_ERR_LOG("[ERROR]Buffer overflows when parsing GET resource.");
			return (KV*)NULL;
		}
		if(src) {
			if(*p=='?') {
				buf[n] = '\0';
				kvs = (KV*)MALLOC(sizeof(KV)* sizeof(char));
				memcpy(kvs->akey, DEF_SRC_NAME, strlen(DEF_SRC_NAME)+1);
				memcpy(kvs->avalue, buf, strlen(buf)+1);

				src = 0;

				break;
			} else {
				buf[n++]=*p;
			}
		}

		++p;
	}

	cur = kvs;

	LNode* pairs = textToList(++p, "&");
	/* preserve the head to the list in order to 
	 * destroy it in the end*/
	LNode* pairs2 = pairs;

	for(; pairs!=NULL; pairs=pairs->pnext) {
		KV* p = api_lineToKV(pairs->avalue, "=");
		/* append the new KV node to the end of KV list */
		cur->pnext = p;
		p->pnext = (KV*)NULL;
		cur = p;
	}

	freeListNode(pairs2);

	return kvs;
}











#endif
